#include "WebModule.h"
#include "../Utility/Log/TraceLog.h"
#include "../Utility/CJson/WebCommonOutputTemplate.h"

#include <set>

struct WebRequstHandlerInfo :JsonReflectionBase
{
    std::string apiMD5Name;
    std::vector<std::string> moduleID;
    int permission;

    WebRequstHandlerType handler;

    std::string apiModuleDesc; //对所在模块的描述，用于日志查询过滤使用

    REFLECT_WEBJSON_OUTPUT_ARGS_NUM(apiMD5Name, moduleID, permission)
};

static std::map<std::string, WebRequstHandlerInfo> s_webRequestHandlers;

int MapServerFunc(const std::string& strWebReq, const std::string& strJsonBuffer, std::string& strStructBuffer)
{
    const auto it = s_webRequestHandlers.find(strWebReq);
    if (it == s_webRequestHandlers.end())
        return -1;

    cJSON *pInputJson = cJSON_Parse(strJsonBuffer.c_str());
    if (nullptr == pInputJson)
    {
        TRACE_LOG_A(nullptr, "TRACE_LOG_LEVEL_ERROR", "%s\n", "cJSON_Parse error");
        return -1;
    }
    std::shared_ptr<void> raii_release_input_json(pInputJson, [](cJSON* ptr){
        cJSON_Delete(ptr);
    });

    int ret = 0;
    std::string output;
    try
    {
        int ret = it->second.handler(pInputJson, output);
    }
    catch(const std::exception& e)
    {
        TRACE_LOG_A(nullptr, "TRACE_LOG_LEVEL_ERROR", "%s\n", e.what());
    }

    if (0 != ret)
    {
        TRACE_LOG_A(nullptr, "TRACE_LOG_LEVEL_ERROR", "%d\n", ret);
    }
    strStructBuffer = output;

    return 0;
}


struct WebAPIGetAPIInfoListInput :JsonReflectionBase
{
    std::string token;

    REFLECT_WEBJSON_INPUT_ARGS_NUM(token)
};

struct WebAPIGetAPIInfoListOutput :JsonReflectionBase
{
    std::vector<WebRequstHandlerInfo> list;

    REFLECT_WEBJSON_OUTPUT_ARGS_NUM(list)
};

int WebAPIGetAPIInfoListOper(const WebAPIPermission permission, WebAPIGetAPIInfoListInput& input, WebAPIGetAPIInfoListOutput& output, std::string& desc)
{
    static std::vector<WebRequstHandlerInfo> list;
    if (list.empty())
    {
        for (auto& x : s_webRequestHandlers)
        {
            list.push_back(x.second);
        }
    }
    output.list = list;
    return 0;
}

int WebAPIGetAPIInfoList(const WebAPIPermission permission, cJSON* pJson, std::string& strJsonBuffer)
{
    WebAPIGetAPIInfoListInput input;
    WebAPIGetAPIInfoListOutput output;

    return GenaralOperator<decltype(input), decltype(output)>(pJson, strJsonBuffer, input, output,
        std::bind(&WebAPIGetAPIInfoListOper, permission, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

struct WebAPITestApiInput :JsonReflectionBase
{
    int input;

    REFLECT_WEBJSON_INPUT_ARGS_NUM(input)
};

struct WebAPITestApiOutput :JsonReflectionBase
{
    int output;

    REFLECT_WEBJSON_OUTPUT_ARGS_NUM(output)
};

int WebAPITestApiOper(const WebAPIPermission permission, WebAPITestApiInput& input, WebAPITestApiOutput& output, std::string& desc)
{
    output.output = input.input + 10;
    return 0;
}

int WebAPITestApi(const WebAPIPermission permission, cJSON* pJson, std::string& strJsonBuffer)
{
    WebAPITestApiInput input;
    WebAPITestApiOutput output;

    return GenaralOperator<decltype(input), decltype(output)>(pJson, strJsonBuffer, input, output,
        std::bind(&WebAPITestApiOper, permission, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
}


//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


bool WebModule::InitModule()
{
    {
        WebModule::Get().RegisterWebInterface("_webserver_GetAPIInfoList", &WebAPIGetAPIInfoList, { "Get API List", "System", WebAPIOperationPermission::View,  {""} } );
        WebModule::Get().RegisterWebInterface("_webserver_TestApi", &WebAPITestApi, { "Test Api", "System", WebAPIOperationPermission::View,  {""} } );
    }

    return true;
}

bool WebModule::RegisterWebInterface(const std::string& request_target, WebRegisterRequstHandlerType handler, const WebAPIPermission permission)
{
    if (s_webRequestHandlers.find(request_target) != s_webRequestHandlers.end())
    {
        //TRACE_LOG_A(nullptr, "TRACE_LOG_LEVEL_ERROR", "%s %s\n", request_target, "httpapi already existed");
        return false;
    }

    WebRequstHandlerInfo info;

    const std::string& prefix = "_webserver_";

    if (request_target.find(prefix) != std::string::npos)
    {
        info.apiMD5Name = request_target.substr(prefix.size());
    }
    else
    {
        info.apiMD5Name = request_target;
    }

    info.moduleID = permission.moduleID;
    info.permission = static_cast<int>(permission.operaPermission);
    info.handler = std::bind(handler, permission, std::placeholders::_1, std::placeholders::_2);
    info.apiModuleDesc = permission.apiModuleDesc;

    s_webRequestHandlers[request_target] = info;

    return true;
}


WebModule& WebModule::Get()
{
    static WebModule webModule;
    return webModule;
}

